﻿using System;
using System.Collections.Generic;

using agsXMPP.protocol.client;

using VSTalk.Engine.Core.Context;

using VSTalk.Model;
using VSTalk.Tools;

namespace VSTalk.Engine.Core.XmppConnection.PresenceListener
{
    public class MultiClientPresenceListener : IPresenceListener
    {
        private static IModelContext ModelContext
        {
            get { return AppServices.Get<IModelContext>(); }
        }

        private readonly IDictionary<Client, SingleClientPresenceListener> _presenceListeners = new Dictionary<Client, SingleClientPresenceListener>();

        private ISubscription _clientSub;

        public void StartListen()
        {
            _clientSub = ModelContext.Clients.HandleCollectionChanges(initialOrAdd: SubscribeClient, removed: UnsubscribeClient);
        }

        public void StopListen()
        {
            foreach (var presenceListener in _presenceListeners)
            {
                presenceListener.Value.StopListen();
            }
            _clientSub.Unsubscribe();
        }

        private void SubscribeClient(Client client)
        {
            var presenceListener = new SingleClientPresenceListener(client);
            _presenceListeners.Add(client, presenceListener);
            presenceListener.PresenceReceived += PresenceListenerOnPresenceReceived;
            presenceListener.StartListen();
        }

        private void PresenceListenerOnPresenceReceived(Client client, Presence presence)
        {
            OnPresenceReceived(client, presence);
        }

        private void UnsubscribeClient(Client client)
        {
            if (!_presenceListeners.ContainsKey(client))
            {
                return;
            }
            var listener = _presenceListeners[client];
            listener.PresenceReceived -= PresenceListenerOnPresenceReceived;
            listener.StopListen();
            _presenceListeners.Remove(client);
        }

        public event Action<Client, Presence> PresenceReceived;
        protected virtual void OnPresenceReceived(Client arg1, Presence arg2)
        {
            var handler = PresenceReceived;
            if (handler != null) handler(arg1, arg2);
        }
    }
}